<?php

declare(strict_types=1);

namespace App\Service;

use Hyperf\Di\Annotation\Inject;
use App\Dao\AdminLogDao;
use App\Dao\CouponDao;
use App\Dao\CouponBatchDao;
use App\Dao\CouponLogDao;
use App\Dao\CouponStatisticsDao;
use App\Dao\LotteryPrizeDao;
use App\Exception\BusinessException;
use Hyperf\AsyncQueue\Driver\DriverFactory;
use App\Constants\ErrorCode;
use App\Utils\ServerUtil;
use Hyperf\DbConnection\Db;
use Hyperf\Utils\ApplicationContext;

/**
 * 优惠券模块
 *
 * @Author czm
 * @DateTime 2020-05-28
 */
class CouponService
{

  /**
   * @Inject
   * @var AdminLogDao
   */
  protected $adminLogLogic;

  /**
   * @Inject
   * @var CouponDao
   */
  protected $couponDao;

  /**
   * @Inject
   * @var CouponBatchDao
   */
  protected $couponBatchDao;


  /**
   * @Inject
   * @var CouponLogDao
   */
  protected $couponLogDao;

  /**
   * @Inject
   * @var CouponStatisticsDao
   */
  protected $couponStatisticsDao;

  /**
   * @Inject
   * @var LotteryPrizeDao
   */
  protected $lotteryPrizeDao;

  /**
   * 明细记录-红包明细-红包日志列表
   * @Author czm
   * @DateTime 2020-04-16
   * @return void
   */
  public function list($params)
  {
    return $this->couponLogDao->pageByWhere($params['where'] ?? [], $params, [], $params);
  }

  /**
   *系统设置-红包券分页列表
   *czm 2020/4/17
   */
  public function batchPageList($params)
  {
    return $this->couponBatchDao->pageByWhere($params['where'] ?? [], $params, [], $params);
  }

  
  /**
   *系统设置-红包券列表
   *czm 2020/4/17
   */
  public function batchList($params)
  {
    return $this->couponBatchDao->getByWhere($params['where'] ?? [], $params);
  }

  /**
   * 优惠券记录导出
   * @Author czm
   * @DateTime 2020-06-04
   * @param [type] $start_time
   * @param [type] $end_time
   * @return string
   */
  public function outputLog($params){

   
    $head=['id','openid','优惠券Id','订单号','优惠券识别码','类型','类型说明','抽奖记录id','红包金额','创建时间','变更时间','红包开始时间','红包结束时间'];
    return $this->couponLogDao->outputLog($params,$head);
  }

  /**
   * 系统设置-红包券-返回批次码 只兼容累计3位数
   * czm 2020/4/17
   */
  public function getBatch()
  {
    $timeFormat = date("Ymd");
    $batch = $this->couponBatchDao->getBatch($timeFormat);
    if (empty($batch)) {
      $data = (int) ("$timeFormat" . "001");
    } else {
      $data = ++$batch;
    }
    return $data;
  }
  /**
   * 系统设置-红包券-生成红包券
   * czm 2020/4/17
   */
  public function generateCoupon($params)
  {
    if ($this->couponBatchDao->existsByWhereTrait(['batch' => $params['batch']])) {
      throw new BusinessException(ErrorCode::ERR_BUESSUS, '该批次已存在！请重新获取批次');
    }
    $insert = array_intersect_key($params, array_flip(['batch', 'name', 'type', 'number', 'amount', 'condition_amount', 'start_time', 'end_time']));
    $batchObj = $this->couponBatchDao->addTrait($insert);
    //组装红包数据
    $couponArr = [
      'batch_id' => $batchObj->id,
      'last_time' => time(),
      'add_time' => time(),
    ];
    //获取最大id
    $maxId = $this->couponDao->getMaxId();
    $insertArr = [];
    for ($i = 0; $params['number'] > $i; $i++) {
      $couponArr['unique_num'] = ServerUtil::cipher(++$maxId);
      $insertArr[] = $couponArr;
    }
    if (!empty($insertArr)) {
      //使用消息队列
      $data = [
        'insertArr' => $insertArr,
        'batch_id' => $batchObj->id,
      ];
      $driver = ApplicationContext::getContainer()->get(DriverFactory::class)->get('coupon_generate');
      $driver->push(new \App\Job\CouponGenerateJob($data));
    }
    //添加管理员操作日记
    $this->adminLogLogic->addLog('生成了红包券批次' . $batchObj->toJson(JSON_UNESCAPED_UNICODE));
  }

  //批量新增红包
  public function couponAdd($params)
  {
    $this->couponDao->insertTrait($params);
  }

  /**
   * 系统设置-红包券-批次编辑 暂时只允许编辑name
   * czm 2020/4/17
   */
  public function batchEdit($params)
  {
    $logInfo = $this->couponBatchDao->findTrait($params['id'])->toJson(JSON_UNESCAPED_UNICODE);
    $this->couponBatchDao->updateTrait($params);
    $this->adminLogLogic->addLog('批次编辑' . $logInfo . '编辑后' . $this->couponBatchDao->findTrait($params['id'])->toJson(JSON_UNESCAPED_UNICODE));
  }

  /**
   * 系统设置-红包券-查看批次ID下所有识别码
   * czm 2020/4/17
   */
  public function couponBatch($params)
  {
    return $this->couponDao->pageByWhere(['batch_id' => $params['batch_id']], $params, ['unique_num', 'status']);
  }
  /**
   * 系统设置-红包券-删除批次 只删除未使用的
   * czm 2020/4/17
   */
  public function batchDel($id)
  {
    if ($this->lotteryPrizeDao->existsByWhereTrait(['batch_id' => $id, 'is_del' => 1, 'status' => 1])) {
      throw new BusinessException(ErrorCode::ERR_BUESSUS, '抽奖奖品批次存在关联无法删除');
    }
    $logInfo = $this->couponBatchDao->findTrait($id)->toJson(JSON_UNESCAPED_UNICODE);
    $this->couponBatchDao->updateTrait(['id' => $id, 'is_del' => 2]);
    $this->couponDao->updateByWhereTrait([['batch_id','=',$id], ['status', '!=', 2]], ['is_del' => 2]);
    $this->adminLogLogic->addLog('删除了红包券批次' . $logInfo);
  }
  /**
   * 数据统计-红包统计
   * @Author czm
   * @DateTime 2020-04-22
   * @return void
   */
  public function statistics($params)
  {
    return $this->couponStatisticsDao->pageByWhere($params['where'], $params);
  }
  /**
   * 数据统计-红包对比
   * @Author czm
   * @DateTime 2020-04-22
   * @return void
   */
  public function compare($params)
  {
    //分两条sql查询数据
    $end = $this->couponStatisticsDao->firstByWhereTrait(['date' => date('Y/m/d', $params['end_time'])]);
    // if (empty($end)) {
    //     throw new BusinessException(ErrorCode::ERR_BUESSUS, '红包券对比截至时间未检测统计数据！(截至日期需小于今天，系统当天数据次日统计生成)');
    // }
    $start = $this->couponStatisticsDao->firstByWhereTrait(['date' => date('Y/m/d', $params['start_time'])]);
    $data = [
      'amount' => [
        'use_amount' => abs(($end['use_amount']?? 0) - ($start['use_amount'] ?? 0)),
        'not_use_amount' => abs(($end['not_use_amount']?? 0) - ($start['not_use_amount'] ?? 0)),
        'expire_amount' => abs(($end['expire_amount']?? 0) - ($start['expire_amount'] ?? 0)),
      ],
      'num' => [
        'use_num' => abs(($end['use_num']?? 0) - ($start['use_num'] ?? 0)),
        'not_use_num' => abs(($end['not_use_num']?? 0) - ($start['not_use_num'] ?? 0)),
        'expire_num' => abs(($end['expire_num']?? 0) - ($start['expire_num'] ?? 0)),
      ],
    ];
    return $data;
  }


  /**
     * 检测根据用户openid是否有可用优惠券
     * @Author czm
     * @DateTime 2020-04-21
     * @param [type] $openid
     * @return boolean
     */
    public function isHasCoupon($openid)
    {
        return $this->couponDao->isHasCoupon($openid);
    }

    /**
     * 根据用户openid获取优惠券列表信息
     * @Author czm
     * @DateTime 2020-04-21
     * @param [type] $openid
     * @param [type] $flag 1 查询所有  2 查询可用
     * @return array|null
     */
    public function getUserCoupon($openid, $flag = 1)
    {
      return $this->couponDao->getUserCoupon($openid, $flag);
    }


  /**
   * status 0未领取 1 未使用 2已使用 3已过期 4已禁用 5未生效
   * @Author czm
   * @DateTime 2020-04-22
   * @param [type] $openid  openid
   * @param [type] $coupon_id 优惠券id
   * @param [type] $flag 1不限制状态 2限制可用状态 
   * @return array
   */
  public function getCouponByCondition($openid, $coupon_id, $flag = 1)
  {
    return $this->couponDao->getCouponByCondition($openid, $coupon_id, $flag);
  }


  /**
   * status 0未领取 1 未使用 2已使用 3已过期 4已禁用 5未生效
   * @Author czm
   * @DateTime 2020-04-23
   * @param [type] $openid
   * @param [type] $coupon_id
   * @param integer $flag 1标记使用 2领取优惠券 3恢复优惠券
   * @param string $order_no 订单号
   * @param integer $type_explain 订单号
   * @return array
   */
  public function updateCoupon($openid, $coupon_id, $flag = 1, $order_no = '',$type_explain=0)
  {   
    return $this->couponDao->updateCoupon($openid, $coupon_id, $flag , $order_no,$type_explain);
  }

  /**
   * 统计红包情况
   * @Author czm
   * @DateTime 2020-04-30
   * @return void
   */
  public function addstatistics()
  { 
    return $this->couponDao->addstatistics();
  }

  /**
   * 领取优惠券
   * @Author czm
   * @DateTime 2020-04-30
   * @return void
   */
  public function receive($params)
  {
    $info=$this->couponDao->firstWithBatchByWhere(['id'=>$params['coupon_id'],'openid'=>$params['openid']]);
    if(empty($info)){
      throw new BusinessException(ErrorCode::ERR_BUESSUS, '优惠券已被领取');
    }
    if($info->status!=1){
      throw new BusinessException(ErrorCode::ERR_BUESSUS, '优惠券不可领取');
    }
    Db::beginTransaction();
    try{
        $oldOpenid=$info->openid;
        //重新绑定红包
        $this->couponDao->updateTrait([
          'share_time'=>time(),
          'id'=>$params['coupon_id'],
          'openid'=>$params['jwt'],
        ]);

        $insetArr=[
            [
                'openid'=>$oldOpenid,
                'coupon_id'=> $params['coupon_id'],
                'unique_num'=>$info->unique_num,
                'type'=>2,
                'type_explain'=>2,
                'amount'=>$info->couponBatch->amount,
                'add_time'=>time(),
                'update_time'=>time(),
                'start_time'=>$info->couponBatch->start_time,
                'end_time'=>$info->couponBatch->end_time,
            ],
            [
                'openid'=>$params['jwt'],
                'coupon_id'=> $params['coupon_id'],
                'unique_num'=>$info->unique_num,
                'type'=>1,
                'type_explain'=>4,
                'amount'=>$info->couponBatch->amount,
                'add_time'=>time(),
                'update_time'=>time(),
                'start_time'=>$info->couponBatch->start_time,
                'end_time'=>$info->couponBatch->end_time,
            ],
        ];
        $this->couponLogDao->insertTrait($insetArr);
        Db::commit();
      }catch(\Throwable $t){
        ServerUtil::info('领取优惠券',['param'=>$params,'jwt'=> $params['jwt'],'res'=>$t->getMessage()]);
        Db::rollback();
        throw new BusinessException(ErrorCode::ERR_BUESSUS, '领取异常');
    }
  }
}
